package com.xk.utils;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.parser.ParserConfig;
import com.alibaba.fastjson.serializer.SerializerFeature;
import com.fasterxml.jackson.databind.JavaType;
import com.fasterxml.jackson.databind.type.TypeFactory;
import org.springframework.data.redis.serializer.RedisSerializer;
import org.springframework.data.redis.serializer.SerializationException;

import java.nio.charset.Charset;

/**
  *
  *FastJsonRedisSerializer是一个Redis序列化和反序列化器，使用FastJson实现。
  *<br>
  *实现了RedisSerializer接口
 */
public class FastJsonRedisSerializer<T> implements RedisSerializer<T>
{
    //默认字符集UTF-8
    public static final Charset DEFAULT_CHARSET = Charset.forName("UTF-8");
    //需要序列化或反序列化的类
    private Class<T> clazz;
    //设置全局开启autoType功能，防止fastjson反序列化时报错
    static
    {
        ParserConfig.getGlobalInstance().setAutoTypeSupport(true);
    }
    /**
     *
     *FastJsonRedisSerializer构造函数
     *@param clazz 传入需要序列化或反序列化的类
     */
    public FastJsonRedisSerializer(Class<T> clazz)
    {
        super();
        this.clazz = clazz;
    }
    /**
      *
      *序列化
      *@param t 需要序列化的对象
      *@return 返回序列化后的字节数组
      *@throws SerializationException 序列化异常
     */
    @Override
    public byte[] serialize(T t) throws SerializationException
    {
        if (t == null)
        {
            return new byte[0];
        }
        //使用FastJson将对象序列化为JSON字符串，再将字符串转为字节数组
        return JSON.toJSONString(t, SerializerFeature.WriteClassName).getBytes(DEFAULT_CHARSET);
    }
    /**
      *
      *反序列化
      *@param bytes 需要反序列化的字节数组
      *@return 返回反序列化后的对象
      *@throws SerializationException 反序列化异常
     */
    @Override
    public T deserialize(byte[] bytes) throws SerializationException
    {
        if (bytes == null || bytes.length <= 0)
        {
            return null;
        }
        //将字节数组转为字符串，再使用FastJson将JSON字符串反序列化为对象
        String str = new String(bytes, DEFAULT_CHARSET);

        return JSON.parseObject(str, clazz);
    }

    /**
      *
      *获取需要序列化或反序列化的类的JavaType
      *@param clazz 需要序列化或反序列化的类
      *@return 返回JavaType对象
     */
    protected JavaType getJavaType(Class<?> clazz)
    {
        return TypeFactory.defaultInstance().constructType(clazz);
    }
}
